from datetime import datetime, timedelta
import smtplib
from django.db.utils import IntegrityError
from django.http import HttpResponse
from django.conf import settings
from django.template.loader import render_to_string
from django.template import RequestContext
from django.utils import simplejson
from django.db import transaction
from django.core.mail import send_mail
from django.utils.encoding import force_unicode
import magic, os, logging, shutil
from mitems.forms import CommentForm, LikeForm, CommentLikeForm,\
    AirtimeForm, FacebookForm, TwitterForm, FollowForm,\
    InquestionForm, FollowFormProfile, FollowFormBroadCast, RepostForm
from mitems.tools.utils import post_to_twitter, ajax_login_required, convert_timezone
from mitems.models import Item, UserProfile, Follower, Comment, ItemImage
from mitems.tools.utils import make_upload_path, resize_save_file, TwitterError
from mitems.views import get_dev_items, get_related_items
from mitems.tools import notify

log = logging.getLogger(__name__)

def prepare_json_response(data):
    return HttpResponse(simplejson.dumps(data), mimetype='application/json')

def prepare_regular_response(data):
    return HttpResponse(simplejson.dumps(data))

def set_cookie(request, response, category, user_category, country):
    if str(category) != request.COOKIES.get('category', '0'):
        response.set_cookie('category', category, max_age=settings.COOKIE_MAX_AGE)
    if str(user_category) != request.COOKIES.get('user_category', '0'):
        response.set_cookie('user_category', user_category, max_age=settings.COOKIE_MAX_AGE)
    if country != request.COOKIES.get('country'):
        response.set_cookie('country', country, max_age=settings.COOKIE_MAX_AGE)


@ajax_login_required
def ajax_picture_upload(request):

    if request.is_ajax():
        filename = request.REQUEST.get('qqfile')
        if not filename:
            return prepare_regular_response({'error': 'no file'})
        size = int(request.META.get('CONTENT_LENGTH'))
        content = request.read()
    elif request.method == 'POST':
        file = request.FILES.get('qqfile')
        if not file:
            return prepare_regular_response({'error': 'no file'})
        filename = file.name
        size = file.size
        content = file.read()
    else:
        return prepare_regular_response({'error': 'no file'})

    if size > settings.IMAGE_LIMIT_SIZE:
        return prepare_regular_response(settings.IMAGE_UPLOADING_ERROR)

    content_type = magic.from_buffer(content, mime=True)
    if not content_type.startswith('image'):
        return prepare_regular_response(settings.IMAGE_UPLOADING_ERROR)

    filename_small = os.path.join(settings.MEDIA_ROOT,
                                        make_upload_path(None, None))
    filename_big = os.path.join(settings.MEDIA_ROOT,
                                        make_upload_path(None, None))
    file_url = os.path.join(settings.MEDIA_URL,
                                os.path.basename(filename_small))
    if not resize_save_file(filename_small, content, settings.IMAGE_SIZE):
        return prepare_regular_response(settings.IMAGE_UPLOADING_ERROR)
    try:
        with open(filename_big, 'wb+') as destination:
            destination.write(content)
    except IOError:
            return prepare_regular_response(settings.IMAGE_UPLOADING_ERROR)

    return prepare_regular_response({'success': {'url': file_url,
                                                    'filename': {
                                                        'small': os.path.basename(filename_small),
                                                        'big': os.path.basename(filename_big)
                                                    }
                                                }
                                    }
    )


@ajax_login_required
def comment_upload(request, story=False):
    form = CommentForm(request.POST or None)
    error = 'Cannot comment item'
    if form.is_valid():
        profile = form.cleaned_data['profile']
        comment = form.save(commit=False)
        comment.user = request.user
        try:
            comment.save()
        except Exception as err:
            log.error(err)
            return prepare_json_response({'error': '%s, %s' % (error, err)})
        item = comment.item
        item.opacity = item.item_get_opacity() if not profile else 1
        item.airtime_left = item.item_airtime_left()
        profile_user = None
        if profile:
            try:
                profile_user = UserProfile.objects.get(pk=int(profile))
            except (ValueError, UserProfile.DoesNotExist):
                pass
        if story:
            comments = item.items_comment.order_by('-id')[:settings.MAX_RESPONSES]
            all_comments = item.items_comment.count()
            more_responses = True if all_comments > settings.MAX_RESPONSES else False
            related_items = get_related_items(item)
        json = dict(item=render_to_string('story_container.html' if story else 'item_container.html',
                                          locals(), RequestContext(request)))
        return prepare_json_response(json)
    return prepare_json_response({'error': error})


@ajax_login_required
def item_like(request, story=False):
    form = LikeForm(request.POST or None)
    error = 'Cannot like item'
    if form.is_valid():
        profile = form.cleaned_data['profile']
        like = form.save(commit=False)
        like.user = request.user
        try:
            like.save()
        except Exception as err:
            log.error(err)
            return prepare_json_response({'error': '%s, %s' % (error, err)})
        item = like.item
        item.opacity = item.item_get_opacity() if not profile else 1
        item.airtime_left = item.item_airtime_left()
        profile_user = None
        if profile:
            try:
                profile_user = UserProfile.objects.get(pk=int(profile))
            except (ValueError, UserProfile.DoesNotExist):
                pass
        if story:
            comments = item.items_comment.order_by('-id')[:settings.MAX_RESPONSES]
            all_comments = item.items_comment.count()
            more_responses = True if all_comments > settings.MAX_RESPONSES else False
            related_items = get_related_items(item)
        json = dict(item=render_to_string('story_container.html' if story else 'item_container.html',
                                          locals(), RequestContext(request)))
        return prepare_json_response(json)
    return prepare_json_response({'error': error})


@ajax_login_required
def item_delete(request, story=False):
    error = 'Cannot delete item'
    if request.method != 'POST':
        return prepare_json_response({'error': error})
    item_id = request.POST.get('item')
    if not item_id:
        return prepare_json_response({'error': error})
    try:
        item = Item.objects.get(pk=item_id, created_by=request.user)
    except Item.DoesNotExist:
        log.error('cannot get item to delete %s: %s' % (item_id, request.user))
        return prepare_json_response({'error': error})
    try:
        item.delete()
    except Exception as err:
        log.error('delete item %s: %s' % (item_id, err))
        return prepare_json_response({'error': '%s, %s' % (error, err)})
    return prepare_json_response({'item': '', 'story': story})


@ajax_login_required
def item_repost(request):
    """Report old item for elite user"""
    form = RepostForm(request.POST or None)
    error = 'Cannot re-post item'
    if not form.is_valid():
        return prepare_json_response({'error': error})
    item_id = form.cleaned_data['id']
    try:
        item = Item.objects.get(pk=item_id, created_by=request.user,
                                created_by__is_elite=True, slumped=True, is_reposted=False)
    except Item.DoesNotExist:
        log.error('cannot get item to re-post %s: %s' % (item_id, request.user))
        return prepare_json_response({'error': error})
    item_dict = dict(message=item.message, description=item.description, tag=item.tag, category=item.category,
                     created_by = request.user, updated_by = request.user, location = item.location,
                     is_active = True, is_mail = item.is_mail, is_feed=item.is_feed)
    picture_small = item.get_small_image()
    picture_big = item.get_big_image()
    new_picture_small, new_picture_big = None, None
    if picture_small:
        try:
            new_picture_small = os.path.join(settings.MEDIA_ROOT, make_upload_path())
            shutil.copyfile(picture_small.image.path, new_picture_small)
        except IOError as err:
            log.error('cannot copy item image %s'%err)
            return prepare_json_response({'error': error})
    if picture_big:
        try:
            new_picture_big = os.path.join(settings.MEDIA_ROOT, make_upload_path())
            shutil.copyfile(picture_big.image.path, new_picture_big)
        except IOError as err:
            log.error('cannot copy item image %s: %s'%err)
            return prepare_json_response({'error': error})
    new_item = Item.objects.create(**item_dict)
    if new_picture_small:
        ItemImage(image=os.path.basename(new_picture_small), item=new_item, size='small').save()
    if new_picture_big:
        ItemImage(image=os.path.basename(new_picture_big), item=new_item, size='big').save()
    item.is_reposted = True
    item.save()
    return prepare_json_response({'url': ''})


@ajax_login_required
def comment_delete(request, story=False):
    error = 'Cannot delete comment'
    if request.method != 'POST':
        return prepare_json_response({'error': error})
    try:
        comment_id = int(request.POST.get('comment'))
    except Exception:
        return prepare_json_response({'error': error})
    try:
        comment = Comment.objects.get(pk=comment_id, user=request.user)
    except Comment.DoesNotExist:
        log.error('cannot get comment to delete %s: %s' % (comment_id, request.user))
        return prepare_json_response({'error': error})
    item = comment.item
    try:
        comment.delete()
    except Exception as err:
        log.error('cannot delete comment %s: %s' % (comment_id, err))
        return prepare_json_response({'error': '%s, %s' % (error, err)})
    profile = request.POST.get('profile')
    item.opacity = item.item_get_opacity() if not profile else 1
    item.airtime_left = item.item_airtime_left()
    profile_user = None
    if profile:
        try:
            profile_user = UserProfile.objects.get(pk=int(profile))
        except (ValueError, UserProfile.DoesNotExist):
            pass
    if story:
        comments = item.items_comment.order_by('-id')[:settings.MAX_RESPONSES]
        all_comments = item.items_comment.count()
        more_responses = True if all_comments > settings.MAX_RESPONSES else False
        related_items = get_related_items(item)
    json = dict(item=render_to_string('story_container.html' if story else 'item_container.html',
                                        locals(), RequestContext(request)))
    return prepare_json_response(json)


@ajax_login_required
def item_airtime(request, story=False):
    form = AirtimeForm(request.POST or None)
    error = 'Cannot add airtime to item'
    if form.is_valid():
        profile = form.cleaned_data['profile']
        airtime = form.save(commit=False)
        if airtime.item.created_by != request.user or not airtime.count:
            return prepare_json_response({'error': error})
        available_airtime = airtime.item.item_airtime_left()
        if available_airtime < airtime.count:
            airtime.count = available_airtime
        if not airtime.count:
            return prepare_json_response({'error': error})
        airtime.user = request.user
        try:
            airtime.save()
        except Exception as err:
            log.error(err)
            return prepare_json_response({'error': '%s, %s' % (error, err)})
        item = airtime.item
        item.opacity = item.item_get_opacity() if not profile else 1
        item.airtime_left = item.item_airtime_left()
        profile_user = None
        if profile:
            try:
                profile_user = UserProfile.objects.get(pk=int(profile))
            except (ValueError, UserProfile.DoesNotExist):
                pass
        if story:
            comments = item.items_comment.order_by('-id')[:settings.MAX_RESPONSES]
            all_comments = item.items_comment.count()
            more_responses = True if all_comments > settings.MAX_RESPONSES else False
            related_items = get_related_items(item)

        json = dict(item=render_to_string('story_container.html' if story else 'item_container.html',
                                          locals(), RequestContext(request)))
        return prepare_json_response(json)
    return prepare_json_response({'error': error})


@ajax_login_required
def comment_like(request):
    like_form = CommentLikeForm(request.POST or None)
    error = 'Cannot like response'
    if like_form.is_valid():
        like = like_form.save(commit=False)
        like.user = request.user
        try:
            like.save()
        except Exception as err:
            log.error(err)
            return prepare_json_response({'error': '%s, %s' % (error, err)})
        comment = like.comment
        json = dict(item=render_to_string('response.html', locals(), RequestContext(request)))
        return prepare_json_response(json)
    return prepare_json_response({'error': error})


@ajax_login_required
def item_facebook(request, story=False):
    form = FacebookForm(request.POST or None)
    error = 'Cannot share item'
    if form.is_valid():
        profile = form.cleaned_data['profile']
        description = form.cleaned_data['message']
        url = form.cleaned_data['url']
        photo = form.cleaned_data['photo']
        message = form.cleaned_data['facebook_message']
        try:
            log.info('start facebook sending %s' % url)
            post = request.graph.me.feed.post(
                message=force_unicode(message),
                picture=photo or '',
                link=url,
                name=force_unicode(description),
                description=settings.FACEBOOK_MESSAGE
                )
            if not post:
                return prepare_json_response({'error': error})
            log.info('end facebook sending %s' % url)
        except Exception as err:
            log.error(err)
            return prepare_json_response({'error': '%s, %s' % (error, err)})
        share = form.save(commit=False)
        share.user = request.user
        share.provider = 'facebook'
        try:
            share.save()
        except Exception as err:
            log.error(err)
            return prepare_json_response({'error': '%s, %s' % (error, err)})
        item = share.item
        item.opacity = item.item_get_opacity() if not profile else 1
        item.airtime_left = item.item_airtime_left()
        profile_user = None
        if profile:
            try:
                profile_user = UserProfile.objects.get(pk=int(profile))
            except (ValueError, UserProfile.DoesNotExist):
                pass
        if story:
            comments = item.items_comment.order_by('-id')[:settings.MAX_RESPONSES]
            all_comments = item.items_comment.count()
            more_responses = True if all_comments > settings.MAX_RESPONSES else False
            related_items = get_related_items(item)

        json = dict(item=render_to_string('story_container.html' if story else 'item_container.html',
                                          locals(), RequestContext(request)))
        return prepare_json_response(json)
    return prepare_json_response({'error': error})


@ajax_login_required
def item_twitter(request, story=False):
    form = TwitterForm(request.POST or None)
    error = 'Cannot share item'
    if form.is_valid():
        profile = form.cleaned_data['profile']
        message = form.cleaned_data['message']
        twitter_tokens = request.user.get_twitter_tokens()
        if not twitter_tokens:
            return prepare_json_response({'error': '%s: cannot get twitter access token' % error})
        try:
            post_to_twitter(message, *twitter_tokens)
        except TwitterError as error:
            return prepare_json_response({'error': str(error)})
        share = form.save(commit=False)
        share.user = request.user
        share.provider = 'twitter'
        try:
            share.save()
        except Exception as err:
            log.error(err)
            return prepare_json_response({'error': '%s, %s' % (error, err)})
        item = share.item
        item.opacity = item.item_get_opacity() if not profile else 1
        item.airtime_left = item.item_airtime_left()
        profile_user = None
        if profile:
            try:
                profile_user = UserProfile.objects.get(pk=int(profile))
            except (ValueError, UserProfile.DoesNotExist):
                pass
        if story:
            comments = item.items_comment.order_by('-id')[:settings.MAX_RESPONSES]
            all_comments = item.items_comment.count()
            more_responses = True if all_comments > settings.MAX_RESPONSES else False
            related_items = get_related_items(item)
        json = dict(item=render_to_string('story_container.html' if story else 'item_container.html',
                                          locals(), RequestContext(request)))
        return prepare_json_response(json)
    return prepare_json_response({'error': error})


@ajax_login_required
def user_follow(request, story=False):
    form = FollowForm(request.POST or None)
    error = 'Cannot follow'
    if form.is_valid():
        profile = form.cleaned_data['profile']
        try:
            item_id = int(form.cleaned_data['item'])
        except (TypeError, ValueError) as err:
            log.error(err)
            return prepare_json_response({'error': '%s, %s' % (error, err)})
        follow = form.save(commit=False)
        follow.follower = request.user
        if follow.follow == follow.follower:
            return prepare_json_response({'error': 'It is impossible to follow for itself'})
        try:
            sid = transaction.savepoint()
            follow.save()
            transaction.savepoint_commit(sid)
        except IntegrityError as err:
            log.error(err)
            transaction.savepoint_rollback(sid)
        except Exception as err:
            log.error(err)
        try:
            item = Item.objects.get(pk=item_id)
        except (Exception, Item.DoesNotExist) as err:
            log.error(err)
            return prepare_json_response({'error': '%s, %s' % (error, err)})
        item.opacity = item.item_get_opacity() if not profile else 1
        item.airtime_left = item.item_airtime_left()
        profile_user = None
        if profile:
            try:
                profile_user = UserProfile.objects.get(pk=int(profile))
            except (ValueError, UserProfile.DoesNotExist):
                pass
        if story:
            comments = item.items_comment.order_by('-id')[:settings.MAX_RESPONSES]
            all_comments = item.items_comment.count()
            more_responses = True if all_comments > settings.MAX_RESPONSES else False
            related_items = get_related_items(item)
        json = dict(item=render_to_string('story_container.html' if story else 'item_container.html',
                                          locals(), RequestContext(request)))
        return prepare_json_response(json)
    return prepare_json_response({'error': error})


@ajax_login_required
def user_unfollow(request, story=False):
    form = FollowForm(request.POST or None)
    error = 'Cannot unfollow'
    if form.is_valid():
        profile = form.cleaned_data['profile']
        try:
            item_id = int(form.cleaned_data['item'])
        except (TypeError, ValueError) as err:
            log.error(err)
            return prepare_json_response({'error': '%s, %s' % (error, err)})
        follow = form.save(commit=False)
        follow.follower = request.user
        try:
            record = Follower.objects.get(follow=follow.follow, follower=follow.follower)
        except Follower.DoesNotExist as err:
            log.error(err)
        try:
            record.delete()
        except Exception as err:
            log.error(err)
        try:
            item = Item.objects.get(pk=item_id)
        except Item.DoesNotExist:
            return prepare_json_response({'error': error})
        item.opacity = item.item_get_opacity() if not profile else 1
        item.airtime_left = item.item_airtime_left()
        profile_user = None
        if profile:
            try:
                profile_user = UserProfile.objects.get(pk=int(profile))
            except (ValueError, UserProfile.DoesNotExist):
                pass
        if story:
            comments = item.items_comment.order_by('-id')[:settings.MAX_RESPONSES]
            all_comments = item.items_comment.count()
            more_responses = True if all_comments > settings.MAX_RESPONSES else False
            related_items = get_related_items(item)
        json = dict(item=render_to_string('story_container.html' if story else 'item_container.html',
                                          locals(), RequestContext(request)))
        return prepare_json_response(json)
    return prepare_json_response({'error': error})


def items_more(request, chapter='submit', category=0, user_category=0, country='all'):
    error = 'Cannot show more items'
    if request.method != 'POST':
        return prepare_json_response({'error': error})
    if chapter not in settings.CHAPTERS:
        chapter = 'submit'
    try:
        category = int(category)
        user_category = int(user_category)
    except (ValueError, TypeError) as err:
        log.error('Cannot get category and user number: %s' % err)
        return prepare_json_response({'error': '%s, %s' % (error, err)})
    request_items = []
    try:
        request_items = [int(item) for item in request.POST.getlist('items[]')]
    except (TypeError, ValueError):
        pass
    if not request_items:
        return prepare_json_response({'error': error})
    search = {'slumped' : False}
    if chapter == 'justin':
        search['created__gte'] = datetime.now()-timedelta(seconds=60*8)
    elif chapter == 'popular':
        pass
    elif chapter == 'slumpin':
        search['time_expired__lte'] = datetime.now()+timedelta(seconds=60*2)
    else:
        search['time_expired__lte'] = datetime.now()+timedelta(seconds=60*8)

    if country != 'all':
        search['location'] = country
    if category:
        search['category__id'] = category
    if user_category and request.user.is_authenticated():
        search['created_by__in'] = request.user.get_follows()
    all_items = Item.objects.filter(**search).exclude(pk__in=request_items).\
        order_by('-score', '-time_total')
    rest_items = all_items.count()
    items = all_items[:settings.ITEMS_PER_PAGE]
    more_items = True if rest_items > settings.ITEMS_PER_PAGE else False
    for item in items:
        item.opacity = item.item_get_opacity()
        item.airtime_left = item.item_airtime_left()
    json = dict(item=render_to_string('items_ajax.html', locals(), RequestContext(request)))
    return prepare_json_response(json)


def responses_more(request, item, page=0):
    error = 'Cannot show more responses'
    try:
        item = int(item)
        page = int(page)
    except (ValueError, TypeError) as err:
        log.error('Cannot get item and page number: %s' % err)
        return prepare_json_response({'error': '%s, %s' % (error, err)})
    try:
        item = Item.objects.get(pk=item)
    except Item.DoesNotExist:
        return prepare_json_response({'error': error})
    all_comments = item.items_comment.count()
    comments = item.items_comment.order_by('-id')\
        [page*settings.MAX_RESPONSES:(page+1)*settings.MAX_RESPONSES]
    more_responses = True if all_comments > (page+1)*settings.MAX_RESPONSES else False
    response_page = page+1
    json = dict(item=render_to_string('story_responses.html',
                                      locals(), RequestContext(request)))
    return prepare_json_response(json)


@ajax_login_required
def user_restore_airtime(request):
    user = request.user
    if user.airtime <= settings.MIN_AIRTIME_COUNT:
        user.airtime = settings.DEFAULT_AIRTIME_COUNT
        user.save()
        return prepare_json_response({'airtime': request.user.airtime})
    return prepare_json_response({'airtime': ''})


@ajax_login_required
def user_get_airtime(request):
    return prepare_json_response({'airtime': request.user.airtime})


def items_update(request):
    if request.method != 'POST':
        return prepare_json_response({})
    request_items = []
    try:
        request_items = [int(item) for item in request.POST.getlist('items[]')]
    except (TypeError, ValueError):
        pass
    if not request_items:
        return prepare_json_response({})
    search = {'pk__in': request_items, 'slumped': False}
    items = Item.objects.filter(**search).order_by('-score', '-time_total')
    for item in items:
        item.opacity = item.item_get_opacity()
        item.airtime_left = item.item_airtime_left()
    json = {'items':
                [ {'body':
                       render_to_string('item_container.html', { 'item': item }, RequestContext(request)),
                   'id': item.id } for item in items ]
    }
    return prepare_json_response(json)


@ajax_login_required
def items_airtime(request):
    if request.method != 'POST':
        return prepare_json_response({})
    request_items = []
    try:
        request_items = [int(item) for item in request.POST.getlist('items[]')]
    except (TypeError, ValueError):
        pass
    if not request_items:
        return prepare_json_response({})
    search = {'pk__in': request_items, 'created_by': request.user }
    items = Item.objects.filter(**search)
    json = {'items': [ {'airtime': item.item_airtime_left(), 'id': item.id }  for item in items ],
            'user_airtime': request.user.airtime
    }
    return prepare_json_response(json)


@ajax_login_required
def item_question(request):
    form = InquestionForm(request.POST or None)
    error = 'Cannot inappropriate item'
    if form.is_valid():
        question = form.save(commit=False)
        question.user = request.user
        try:
            question.save()
        except Exception as err:
            log.error(err)
            return prepare_json_response({'error': '%s, %s' % (error, err)})
        item = question.item
        comments = item.items_comment.order_by('-id')[:settings.MAX_RESPONSES]
        item.airtime_left = item.item_airtime_left()
        all_comments = item.items_comment.count()
        related_items = get_related_items(item)
        more_responses = True if all_comments > settings.MAX_RESPONSES else False
        response_page = 1
        story = True
        json = dict(item=render_to_string('story_container.html', locals(),
                                          RequestContext(request)))
        return prepare_json_response(json)
    return prepare_json_response({'error': error})


def items_filter(request, chapter='8live', category=0, user_category=0, country='all'):

    error = 'Cannot filter items'
    if chapter not in settings.CHAPTERS:
        chapter = '8live'
    try:
        category = int(category)
        user_category = int(user_category)
    except (ValueError, TypeError) as err:
        log.error('Cannot get category and user number: %s' % err)
        return prepare_json_response({'error': '%s, %s' % (error, err)})
    search = {'slumped' : False}
    if chapter == 'justin':
        search['created__gte'] = datetime.now()-timedelta(seconds=60*8)
    elif chapter == 'popular':
        pass
    elif chapter == 'slumpin':
        search['time_expired__lte'] = datetime.now()+timedelta(seconds=60*2)
    else:
        search['time_expired__lte'] = datetime.now()+timedelta(seconds=60*8)

    if country != 'all':
        search['location'] = country
    if category:
        search['category__id'] = category
    if user_category and request.user.is_authenticated():
        search['created_by__in'] = request.user.get_follows()

    all_items = Item.objects.filter(**search).order_by('-score', '-time_total')

    rest_items = all_items.count()
    items = all_items[:settings.ITEMS_PER_PAGE]
    more_items = True if rest_items > settings.ITEMS_PER_PAGE else False
    for item in items:
        item.opacity = item.item_get_opacity()
        item.airtime_left = item.item_airtime_left()
    dev_items = get_dev_items(category)
    convert_timezone(dev_items, 'created', request.user, request.META.get('REMOTE_ADDR', '127.0.0.1'))
    json = dict(
        item=render_to_string('items_ajax.html', locals(), RequestContext(request)),
        dev_items=render_to_string('dev_stories.html', locals(), RequestContext(request)))
    response = prepare_json_response(json)
    set_cookie(request, response, category, user_category, country)
    return response


@ajax_login_required
def user_follow_profile(request, right=False):
    form = FollowFormProfile(request.POST or None)
    error = 'Cannot follow'
    if form.is_valid():
        try:
            profile = int(form.cleaned_data['profile'])
        except (ValueError, TypeError) as err:
            return prepare_json_response({'error': '%s, %s' % (error, err)})
        follow = form.save(commit=False)
        follow.follower = request.user
        if follow.follow == follow.follower:
            return prepare_json_response({'error': 'It is impossible to follow for itself'})
        try:
            sid = transaction.savepoint()
            follow.save()
            transaction.savepoint_commit(sid)
        except IntegrityError as err:
            log.error(err)
            transaction.savepoint_rollback(sid)
        except Exception as err:
            log.error(err)
        user_follow = follow.follow
        if profile == request.user.id:
            profile_user = request.user
        else:
            try:
                profile_user = UserProfile.objects.get(pk=profile)
            except UserProfile.DoesNotExist as err:
                return prepare_json_response({'error': '%s, %s' % (error, err)})
        if not right:
            following = profile_user.follows.count()
            followers = profile_user.followers.count()
            json = dict(item=render_to_string('follow_item.html', locals(), RequestContext(request)),
                        following=following, followers=followers)
        else:
            json = dict(item=render_to_string('my_items_right.html', locals(), RequestContext(request)))
        return prepare_json_response(json)
    return prepare_json_response({'error': error})


@ajax_login_required
def user_unfollow_profile(request, right=False):
    form = FollowFormProfile(request.POST or None)
    error = 'Cannot follow'
    if form.is_valid():
        try:
            profile = int(form.cleaned_data['profile'])
        except (ValueError, TypeError) as err:
            return prepare_json_response({'error': '%s, %s' % (error, err)})
        follow = form.save(commit=False)
        follow.follower = request.user
        try:
            record = Follower.objects.get(follow=follow.follow, follower=follow.follower)
        except Follower.DoesNotExist as err:
            log.error(err)
        try:
            record.delete()
        except Exception as err:
            log.error(err)
        user_follow = follow.follow
        if profile == request.user.id:
            profile_user = request.user
        else:
            try:
                profile_user = UserProfile.objects.get(pk=profile)
            except UserProfile.DoesNotExist as err:
                return prepare_json_response({'error': '%s, %s' % (error, err)})
        if not right:
            following = profile_user.follows.count()
            followers = profile_user.followers.count()
            json = dict(item=render_to_string('follow_item.html', locals(), RequestContext(request)),
                        following=following, followers=followers)
        else:
            json = dict(item=render_to_string('my_items_right.html', locals(), RequestContext(request)))
        return prepare_json_response(json)
    return prepare_json_response({'error': error})


@ajax_login_required
def user_send_my_email(request):
    error = 'Cannot send mail'
    if not request.method == "POST":
        return prepare_json_response({'error': error})
    if not request.user.email:
        return prepare_json_response({'error': '<a href="/profile/">Please update your mail</a>'})
    try:
        send_mail(notify.MY_EMAIL_SUBJECT,
                  notify.MY_EMAIL_BODY % request.user.mobile_email,
                  settings.EMAIL_FROM,
                  [request.user.email]
        )
    except smtplib.SMTPException as err:
        return prepare_json_response({'error': '%s: %s' % (error, err)})
    else:
        return prepare_json_response({'success': 'Email has been sent'})

@ajax_login_required
def user_follow_broadcaster(request):
    form = FollowFormBroadCast(request.POST or None)
    error = 'Cannot follow'
    if form.is_valid():
        follow = form.save(commit=False)
        follow.follower = request.user
        if follow.follow == follow.follower:
            return prepare_json_response({'error': 'It is impossible to follow for itself'})
        try:
            sid = transaction.savepoint()
            follow.save()
            transaction.savepoint_commit(sid)
        except IntegrityError as err:
            log.error(err)
            transaction.savepoint_rollback(sid)
        except Exception as err:
            log.error(err)
        broadcaster = follow.follow
        json = dict(item=render_to_string('broadcaster.html', locals(), RequestContext(request)))
        return prepare_json_response(json)
    return prepare_json_response({'error': error})


@ajax_login_required
def user_unfollow_broadcaster(request):
    form = FollowFormBroadCast(request.POST or None)
    error = 'Cannot follow'
    if form.is_valid():
        follow = form.save(commit=False)
        follow.follower = request.user
        try:
            record = Follower.objects.get(follow=follow.follow, follower=follow.follower)
        except Follower.DoesNotExist as err:
            log.error(err)
        try:
            record.delete()
        except Exception as err:
            log.error(err)
        broadcaster = follow.follow
        json = dict(item=render_to_string('broadcaster.html', locals(), RequestContext(request)))
        return prepare_json_response(json)
    return prepare_json_response({'error': error})


@ajax_login_required
def invite_facebook(request):
    """get list of facebook friends"""
    error = 'Cannot get facebook fiends'
    try:
        facebook_friends = request.graph.me.friends().get('data', [])
    except Exception as err:
        log.error('Cannot get facebook fiends for %s: %s' % (request.user, err))
        return prepare_json_response({'error': error})
    return prepare_json_response({'friends': facebook_friends})